package studyguide.ch18;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.ToneControl;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class SoundPlayerMidlet extends MIDlet {

	private static final byte[] sequence;

	static {
		byte tempo = 30; // set tempo to 120 bpm
		byte d = 8; // eighth-note

		byte C4 = ToneControl.C4;
		;
		byte D4 = (byte) (C4 + 2); // a whole step
		byte E4 = (byte) (C4 + 4); // a major third
		byte G4 = (byte) (C4 + 7); // a fifth
		byte rest = ToneControl.SILENCE; // rest

		sequence = new byte[] { ToneControl.VERSION, 1, // version 1
				ToneControl.TEMPO, tempo, // set tempo
				ToneControl.BLOCK_START, 0, // start define "A" section
				E4, d, D4, d, C4, d, E4, d, // content of "A" section
				E4, d, E4, d, E4, d, rest, d, // 
				ToneControl.BLOCK_END, 0, // end define "A" section
				ToneControl.PLAY_BLOCK, 0, // play "A" section
				D4, d, D4, d, D4, d, rest, d, // play "B" section
				E4, d, G4, d, G4, d, rest, d, // 
				ToneControl.PLAY_BLOCK, 0, // repeat "A" section
				D4, d, D4, d, E4, d, D4, d, C4, d // play "C" section
		};
	}

	private final Command exitCommand;
	private final Command playCommand;
	private final Display display;

	private final List audioResources;

	private final TonePlayingForm tonePlayingForm;
	private final MediaPlayingForm mediaPlayingForm;

	private class SampleCommandListener implements CommandListener {
		public void commandAction(Command command, Displayable displayable) {
			if (command == exitCommand) {
				destroyApp(true);
				notifyDestroyed();
			} else if (command == playCommand) {
				int selected = audioResources.getSelectedIndex();
				InputStream stream;
				switch (selected) {
				case 0:
					// Tone
					display.setCurrent(tonePlayingForm);
					break;
				case 1:
					// WAV
					stream = getClass().getResourceAsStream(
							"/sound/sound.wav");
					mediaPlayingForm.initialize(stream, "audio/x-wav");
					display.setCurrent(mediaPlayingForm);
					break;
				case 2:
					// MIDI
					stream = getClass().getResourceAsStream("/sound/music.mid");
					mediaPlayingForm.initialize(stream, "audio/midi");
					display.setCurrent(mediaPlayingForm);
					break;
				case 3:
					// MIDI over HTTP
					// Ran in another thread as the initialization process is blocking
					Thread thread = new Thread( new Runnable() {
						public void run() {
							mediaPlayingForm
								.initialize("http://localhost:8080/JavaMEStudyGuide-Web/music.mid");
							display.setCurrent(mediaPlayingForm);
						}
					});
					thread.start();
					break;
				case 4:
					// Tone sequence
					try {
						Player player = Manager
								.createPlayer(Manager.TONE_DEVICE_LOCATOR);
						// Player must be realized to use the controls
						player.realize();
						ToneControl toneControl = (ToneControl) player
								.getControl("ToneControl");
						toneControl.setSequence(sequence);
						mediaPlayingForm.initialize(player);
						display.setCurrent(mediaPlayingForm);
					} catch (IOException e) {
						throw new RuntimeException("ERROR:" + e);
					} catch (MediaException e) {
						throw new RuntimeException("ERROR:" + e);
					}
					break;
				default:
					throw new RuntimeException("UNKNOWN AUDIO RESOURCE"
							+ command);
				}
			} else {
				throw new RuntimeException("UNKNOWN COMMAND" + command);
			}
		}
	}

	public SoundPlayerMidlet() throws IOException {
		audioResources = new List("Audio Resources", Choice.IMPLICIT);
		exitCommand = new Command("Exit", Command.EXIT, 1);
		playCommand = new Command("Play", Command.SCREEN, 1);

		audioResources.append("Tone", null);
		audioResources.append("PCM WAVE Sound", null);
		audioResources.append("MIDI Music", null);
		audioResources.append("MIDI over HTTP", null);
		audioResources.append("Tone Sequence", null);

		audioResources.setSelectCommand(playCommand);
		audioResources.addCommand(exitCommand);

		SampleCommandListener listener = new SampleCommandListener();
		audioResources.setCommandListener(listener);
		display = Display.getDisplay(this);

		tonePlayingForm = new TonePlayingForm(this);
		mediaPlayingForm = new MediaPlayingForm(this);

		// Display information about device:
		String[] cts = Manager.getSupportedContentTypes(null);
		System.out.println("Supported content types:");
		for (int i = 0; i < cts.length; i++) {
			System.out.println("    " + cts[i]);
		}
		String[] protocols = Manager.getSupportedProtocols(null);
		System.out.println("Supported protocols:");
		for (int i = 0; i < protocols.length; i++) {
			System.out.println("    " + protocols[i]);
		}
	}

	protected void destroyApp(boolean unconditional) {
	}

	protected void pauseApp() {
	}

	protected void startApp() throws MIDletStateChangeException {
		showMainScreen();
	}

	public void showMainScreen() {
		display.setCurrent(audioResources);
	}

}
